// locutor
// (c) 2008-2009, Normen Müller, normen.mueller@gmail.com  
// $Id$
package locutor.model.parsing.grgen

import collection.mutable.HashSet

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
private [grgen] object ExprParser {
  
  val reserved = new HashSet[String] ++ List(
    "int", "double", "float", "string",
    "true", "false", "null",
    "visited", "nameof", "typeof"    
  )
  
  val delimiters = new HashSet[String] ++ List(
    "[", "]", "(", ")",
    "!", "?", ":", ",", ".", "::", 
    "^", "&&", "||", "&", "|",
    "<<", ">>>", ">>", "+", "-", "*", "/", "%", "~",
    "<=", "<", "==", "!=", ">=", ">"    
  )
  
}

/** 
 * Restrictions:
 * - Keyword ``in'' not yet supported
 * 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
private [grgen] trait ExprParser extends BaseParser {
  
  def expr: Parser[Any]          = cond_expr  
  def cond_expr: Parser[Any]     = log_or_expr ~ opt("?" ~ expr ~ ":" ~ cond_expr)  
  def log_or_expr: Parser[Any]   = log_and_expr ~ (("||" ~ log_and_expr)*)
  def log_and_expr: Parser[Any]  = bit_or_expr ~ (("&&" ~ bit_or_expr)*)
  def bit_or_expr: Parser[Any]   = bit_xor_expr ~ (("|" ~ bit_xor_expr)*)
  def bit_xor_expr: Parser[Any]  = bit_and_expr ~ (("^" ~ bit_and_expr)*)
  def bit_and_expr: Parser[Any]  = except_expr ~ (("&" ~ except_expr)*)
  def except_expr: Parser[Any]   = eq_expr ~ (("\\" ~ eq_expr)*)
  def eq_expr: Parser[Any]       = rel_expr ~ ((("==" | "!=") ~ rel_expr)*)
  def rel_expr: Parser[Any]      = shift_expr ~ ((("<=" | "<" | ">=" | ">") ~ shift_expr)*)
  def shift_expr: Parser[Any]    = add_expr ~ ((("<<" | ">>>" | ">>") ~ add_expr)*)
  def add_expr: Parser[Any]      = mul_expr ~ ((("+" | "-") ~ mul_expr)*)
  def mul_expr: Parser[Any]      = unary_expr ~ ((("*" | "%" | "/") ~ unary_expr)*)
  def unary_expr: Parser[Any]    =
    ( ("~" ~ unary_expr) | ("!" ~ unary_expr) | ("-" ~ unary_expr) | ("+" ~ unary_expr)
    | ("(" ~ ("int" | "float" | "double" | "string") ~ ")" ~ unary_expr)
    | (primary_expr ~ ((selector_expr)*))
    )
  def primary_expr: Parser[Any]  =
    ( visited_expr | name_of
    | ident ~ "." ~ ident | ident ~ "::" ~ ident | ident
    | constant
    | type_of
    | "(" ~ expr ~ ")"
    )
  def visited_expr: Parser[Any]  = "visited" ~ "(" ~ ident ~ (("," ~ expr ~ ")") | ")")
  def name_of: Parser[Any]       = "nameof" ~ "(" ~ opt(ident) ~ ")"
  def type_of: Parser[Any]       = "typeof" ~ "(" ~ ident ~ ")"
  def selector_expr: Parser[Any] = (("[" ~ expr ~ "]") | ("." ~ ident ~ opt(param_expr)))
  def param_expr: Parser[Any]    = "(" ~ opt(expr ~ ("," ~ expr)*) ~ ")"
  def constant: Parser[Any]      = numeric | string | "true" | "false" | "null"

}
